home *** CD-ROM | disk | FTP | other *** search
- Path: news.th-darmstadt.de!news
- From: Enno Sandner <enno@intellektik.informatik.th-darmstadt.de>
- Newsgroups: comp.lang.c++
- Subject: Re: Creating a pointer to a function "void (*ptrFunction)()" inside a class
- Date: Fri, 05 Jan 1996 16:00:22 +0100
- Organization: Fachbereich Informatik, TH Darmstadt
- Message-ID: <30ED3D06.59E2B600@intellektik.informatik.th-darmstadt.de>
- References: <30ECA10F.3D99@ifu.net>
- NNTP-Posting-Host: kitz.intellektik.informatik.th-darmstadt.de
- Mime-Version: 1.0
- Content-Type: text/plain; charset=us-ascii
- Content-Transfer-Encoding: 7bit
- X-Mailer: Mozilla 2.0b4 (X11; I; SunOS 4.1.3 sun4m)
-
- Jason Gresh wrote:
- >
- > Hi,
- >
- > I am trying to create a base class that has a function that the
- > derived class needs to create. In order to do this, I want to create a
- > pointer to a function in the base class that the derived class can then
- > define. This is not a case where an override will work because the
- > number and names of the derived functions is not known. Hopefully this
- > code sample will make this clearer:
- >
- > class BaseClass
- > {
- > int (*ptrFunction)();
- > }
- >
- > class DerivedClass : BaseClass
- > {
- > DerivedClass::DerivedClass();
- > int myFunction(int, int);
- > }
- >
- > DerivedClass::DerivedClass()
- > {
- > ptrFunction = myFunction;
- > }
- >
- > DerivedClass::myFunction(int, int)
- > {
- > // code ....
- > }
- >
- > If I don't make myFunction part of the derived class (global),
- > everything works fine. As soon as I include it in the class, I cannot
- > assign a pointer to it. I am aware that pointers to functions inside
- > the class include the class name in some way ( this is not an issue for
- > global functions). What is the casting (or other) mechanism to make
- > this work?
- >
-
- You should forget about casting in this situation.
- The problem is that you try to assign a pointer to
- a member-function to a pointer to an ordinary function.
- The types of both pointers are incompatible.
- When 'myfunction' doesn't access any instance specific
- data (direct or by calling a function that does so),
- you can declare 'myfunction' as static and the problem
- will disappear.
- Otherwise it's not that easy, but a broadly accepted solution
- is to encapsulate (member-) functions in so called functors.
- Usually one starts with a class that describes the common
- interface of all functors of a cathegory. In your example it
- may look like:
-
- class Functor {
- public:
- virtual ~Functor() {}
- virtual int operator()() =0;
- };
-
- All subclasses and therefore all implementations of the Functor
- will provide a realization of 'operator ()'.
- There could for example a class 'CFunctor' which encapsulates
- pointers to ordinary functions:
-
- class CFunctor : public Functor {
-
- typedef int (*F)();
-
- public:
- CFunction(F func) : func_(func) {}
- int operator ()() { return (*func_)(); }
- private:
- F func_;
- };
-
- Another subclass may form a wrapper to member-functions.
- (see below GenFunctor<T>). And finally there're maybe classes
- which does other fancy things.
- Now a possible client of the Functor uses the common interface
- to invoke the offered functionality:
-
- void f(Functor& f) { int i=f(); }
-
- Because 'operator ()' is declared as virtual the correct implementation
- will be used. The client doesn't care how the functionality is invoked
- it just uses the Functor-interface. Thus there're no unnecessary
- dependencies between the client and service provider.
- The following example demonstrates how to wrap arbitary member-functions
- of type 'int (X::*)()' (where X is come class) using the functor-idiom.
-
- Enno
-
- #include <iostream.h>
-
- class Functor {
- public:
- virtual ~Functor() {}
- virtual int operator()() =0;
- };
-
- template<class T> class GenFunctor : public Functor {
-
- typedef int (T::*MF)();
-
- public:
- GenFunctor(T* const obj,MF func) : obj_(obj), func_(func) {}
- int operator()() { return (obj_->*func_)(); }
-
- private:
- T* const obj_;
- MF func_;
- };
-
- void f(Functor& f) { cout << f() << endl; }
-
- struct A { int f() { return 1; } };
- struct B { int f() { return 2; } };
-
- int main()
- {
- A a;
- B b;
- GenFunctor<A> fa(&a,&A::f);
- GenFunctor<B> fb(&b,&B::f);
- f(fa);
- f(fb);
-
- return 0;
- }
-